package com.hitqz.robot.biz.flow.component.patrol;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.system.SystemUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hitqz.robot.api.business.entity.PatrolResultEntity;
import com.hitqz.robot.api.business.enums.MediaEnum;
import com.hitqz.robot.api.business.enums.ResultTypeEnum;
import com.hitqz.robot.api.business.enums.WorkStatusEnum;
import com.hitqz.robot.api.business.model.dto.FlowContextDto;
import com.hitqz.robot.api.business.model.dto.FlowPatrolPreAndEndTicketsDto;
import com.hitqz.robot.api.business.model.dto.FlowPatrolTicketsDto;
import com.hitqz.robot.api.business.model.vo.patrol.PatrolItemVo;
import com.hitqz.robot.api.common.entity.*;
import com.hitqz.robot.api.common.entity.Robot;
import com.hitqz.robot.biz.core.FileProperties;
import com.hitqz.robot.biz.flow.util.LiteFlowUtil;
import com.hitqz.robot.biz.service.*;
import com.hitqz.robot.camera.EquipmentFactory;
import com.hitqz.robot.camera.IEquipmentService;
import com.hitqz.robot.camera.configure.EquipmentCmdEnum;
import com.hitqz.robot.camera.dto.MediaFileDto;
import com.hitqz.robot.camera.dto.QueryParamsDto;
import com.hitqz.robot.camera.dto.TakePicParamsDto;
import com.hitqz.robot.driver.model.IRobotPosDto;
import com.hitqz.robot.driver.parent.RobotDriverService;
import com.sun.jdi.event.ExceptionEvent;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ServerProperties;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutorService;

@Slf4j
@LiteflowComponent(value = "DynamicDetectWithSound", name = "[巡检]动态检测及声音检测")
@AllArgsConstructor
public class DynamicDetectWithSound extends NodeComponent {

    private final RobotService robotService;

    private final RobotEquipmentService robotEquipmentService;

    private final EquipmentFactory equipmentFactory;

    private final PatrolItemService patrolItemService;

    private final PatrolObjectService patrolObjectService;

    private final PatrolCheckTypeService patrolCheckTypeService;


    private final PatrolResultService patrolResultService;

    private final PatrolObjectStandardService patrolObjectStandardService;

    private final ServerProperties serverProperties;

    private final RobotDriverService robotDriverService;

    private final RobotMapPosService robotMapPosService;

    private final FileProperties fileProperties;

    private final ExecutorService dynamicDetectPool;

    @Override
    public void process() throws Exception {
        FlowContextDto dto = this.getRequestData();
        TicketsTask task = dto.getTicketsTask();
        log.info("任务数据 {}", task.getParseOrderParams());
        FlowPatrolTicketsDto params = JSONObject.parseObject(task.getParseOrderParams(), FlowPatrolTicketsDto.class);
        log.info("{} ---params: {}", task.getParseOrderParams(), JSONObject.toJSONString(params));
        FlowPatrolPreAndEndTicketsDto endParams = JSONObject.parseObject(task.getParseOrderParams(), FlowPatrolPreAndEndTicketsDto.class);
        if (params.getPosId() == null && endParams.getEndPosId() == null) {
            log.warn("没有站点信息,不执行");
            return;
        }
        Integer posId = params.getPosId() != null ? params.getPosId() : endParams.getEndPosId();
        dynamicDetectPool.execute(() -> {
            int lastX = 0;
            while (true) {
                try {
                    Thread.sleep(1000);
                    //外部中断
                    LiteFlowUtil.checkInterruptFlag();
                    RobotMapPos robotMapPos = robotMapPosService.getById(posId);
                    IRobotPosDto iRobotPosDto = robotDriverService.getWebPos();
                    Robot robot = robotService.getDefaultRobot();
                    //走过了退出
                    int currentX = (int) iRobotPosDto.getX();
//                    if (robotMapPos.getPosX() < currentX) {
//                        log.info("超过目标点，退出动态检测");
//                        break;
//                    }
                    //不是作业中
                    if (!Objects.equals(robot.getWorkStatus(), WorkStatusEnum.WORK.getCode())) {
                        log.info("patrol=> 非作业，退出动态检测");
                        break;
                    }
                    int i = currentX - lastX;
                    Integer count = 0 ;
                    if (Math.abs(i) > 2000) {
                        log.info("第{}次patrol", count++);
                        dynamicDetectPool.execute(() -> {
                            try {
                                //拍照
                                String relativePath = takePic(params);
                                if (SystemUtil.getOsInfo().isWindows()){
                                    relativePath = relativePath.replace("\\", "/");
                                }
                                log.info("patrol => take photo result {}",relativePath);
                                //检测
                                Integer patrolItemId = params.getPatrolItemId();
                                PatrolItem item = patrolItemService.getById(patrolItemId);
                                PatrolObject patrolObject = patrolObjectService.getById(item.getPatrolObjectId());
                                PatrolCheckType checkType = patrolCheckTypeService.getById(patrolObject.getPatrolCheckTypeId());

                                JSONObject result = detect(params, relativePath);
                                //生成报表
                                writeResult(checkType, task, currentX, i, dto, params, result, relativePath);
                            } catch (Exception e) {
                                log.error(e.getMessage(), e);
                            }
                        });

                        List<PatrolCheckType> list = patrolCheckTypeService.list();
                        Optional<PatrolCheckType> first = list.stream().filter(checkType -> Objects.equals(checkType.getMediaType(), MediaEnum.AUDIO.getType()))
                                .findFirst();
                        if (first.isPresent()) {
                            dynamicDetectPool.execute(() -> {
                                try {
                                    log.info("patrol=> take sound ");
                                    //录音
                                    String ysPath = takeSoundRecord(params);
                                    log.info("patrol=> record sound {}", ysPath);
                                    //检测
                                    JSONObject result = detectSound(first.get(), ysPath);
                                    //生成报表
                                    String relativePath = File.separator + "wav" + File.separator + DateUtil.format(new Date(), "yyyyMMdd") + File.separator + DateUtil.format(new Date(), "yyyyMMddHHmmssSSS") + ".wav";
                                    try{
                                        URL url = new URL(ysPath);
                                        InputStream inputStream = url.openStream();
                                        String path = fileProperties.getLocal().getBasePath() +relativePath;
                                        FileUtil.writeFromStream(inputStream,path);
                                        relativePath = relativePath.replace("\\", "/");
                                    }catch (Exception e){
                                        log.info("下载wav出错",e);
                                    }
                                    writeResult(first.get(), task, currentX, i, dto, params, result, relativePath);
                                }catch (Exception e) {
                                    log.error(e.getMessage(),e);
                                }
                            });
                        }
                        lastX = (int) currentX;
                    }
                    if (Math.abs(robotMapPos.getPosX() - currentX) < 2000) {
                        log.info("patrol=> posX{} currentX{} 距离目标点小于2000，退出动态检测", robotMapPos.getPosX(), currentX);
                        break;
                    }
                } catch (Exception e) {
                    log.info("patrol=> 动态检测异常", e);
                    log.error(e.getMessage(), e);
                    break;
                }
            }

        });
    }
    private void writeResult(PatrolCheckType checkType, TicketsTask task, Integer x, Integer dir, FlowContextDto dto, FlowPatrolTicketsDto params, JSONObject jsonObject, String relativePath) {
        Integer code = jsonObject.getInteger("code");
        String result = "0";
        if (SystemUtil.getOsInfo().isWindows()){
            relativePath = relativePath.replace("\\","/");
        }
        String path = relativePath;
        String normalValue = "0";
        if (Objects.equals(code, 200)) {
            if (StrUtil.isNotBlank(jsonObject.getString("result"))) {
                result = jsonObject.getString("result").replace("a", "").replace("b", "").replace("c", "");
            }
            if (StrUtil.isNotBlank(jsonObject.getString("path"))) {
                String visionPath = downloadImage(jsonObject.getString("path"));
                if (StrUtil.isNotBlank(visionPath)) {
                    if (SystemUtil.getOsInfo().isWindows()){
                        visionPath = visionPath.replace("\\","/");
                    }
                    path = visionPath;
                }
            }
            if (StrUtil.isNotBlank(jsonObject.getString("normal_value"))) {
                normalValue = jsonObject.getString("normal_value");
            }
        }
//        Integer patrolItemId = params.getPatrolItemId();
//        PatrolItem item = patrolItemService.getById(patrolItemId);
//        PatrolObject patrolObject = patrolObjectService.getById(item.getPatrolObjectId());
//        PatrolCheckType checkType = patrolCheckTypeService.getById(patrolObject.getPatrolCheckTypeId());
//        PatrolObjectStandard standard = patrolObjectStandardService.getOne(Wrappers.<PatrolObjectStandard>lambdaQuery().eq(PatrolObjectStandard::getPatrolObjectId, patrolObject.getId()).last("limit 1"));

        //新增
        String direction = dir > 0 ? "-往" : "-返";
        Integer itemId = (x / 1000) * 100 + checkType.getId().intValue();
        String devName = "轨道" + (x / 1000) + "米处" + direction;
        PatrolResultEntity patrolResult = getPatrolResult(task.getTicketsId(), itemId, devName, checkType, path,relativePath, result);

        // 报警
        Runnable runnableTask = () -> {
            //todo 上传到服务端 0-未上传 1-已上传 2-上传失败
            patrolResultService.upload2Server(patrolResult);
            patrolResult.setUploadStatus(1);
            patrolResultService.saveOrUpdate(patrolResult);
        };
        dynamicDetectPool.submit(runnableTask);
    }

    private PatrolResultEntity getPatrolResult(Long ticketsId,Integer itemId,  String devName, PatrolCheckType patrolCheckType,String visionPath,String normalPath,String result){
//        PatrolObject patrolObject = patrolObjectService.getOne(Wrappers.<PatrolObject>lambdaQuery().eq(PatrolObject::getPatrolCheckTypeId, patrolCheckType.getId()).last("limit 1"));
//        PatrolObjectStandard standard = patrolObjectStandardService.getOne(Wrappers.<PatrolObjectStandard>lambdaQuery().eq(PatrolObjectStandard::getPatrolObjectId, patrolObject.getId()).last("limit 1"));

        PatrolObject patrolObject = patrolObjectService.getOne(Wrappers.<PatrolObject>lambdaQuery().eq(PatrolObject::getPatrolCheckTypeId, patrolCheckType.getId()).last("limit 1"));
        PatrolObjectStandard standard = patrolObjectStandardService.getOne(Wrappers.<PatrolObjectStandard>lambdaQuery().eq(PatrolObjectStandard::getPatrolObjectId, patrolObject.getId()).last("limit 1"));

        PatrolResultEntity patrolResult = new PatrolResultEntity();
        patrolResult.setCreateTime(new Date());
        patrolResult.setTicketsId(ticketsId.intValue());
        patrolResult.setDevName(devName);
        patrolResult.setItemId(itemId);
        patrolResult.setItemName(patrolObject.getName());
        patrolResult.setCheckTime(new Date());
        //处理结果数据
        patrolResult.setVisionResult(result);
        patrolResult.setConvertValue(result);
        if (Objects.equals(patrolObject.getIsConvert(), 1) && StrUtil.isNotBlank(result)) {
            // 转换后的值,用来比较和做数据统计的
            // 0-无返回 1-浮点型 2-单个枚举 3-多个枚举 4-字符串 5-数显
            String resultType = patrolCheckType.getResultType();
            ResultTypeEnum resultTypeEnum = ResultTypeEnum.fromType(resultType);
            if (resultTypeEnum != null) {
                switch (resultTypeEnum) {
                    //todo 新增和编辑去检查有没有 ,
                    case FLOAT -> {
                        String[] convertValues = patrolObject.getFloatConvert().split(",");
                        BigDecimal convertMinValue = new BigDecimal(convertValues[0]);
                        BigDecimal convertMaxValue = new BigDecimal(convertValues[1]);
                        BigDecimal visionResult = new BigDecimal(result);
                        double convertValue = visionResult.multiply(convertMaxValue.subtract(convertMinValue)).add(convertMinValue).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        patrolResult.setConvertValue(String.valueOf(convertValue));
                    }
                    case SINGLE_ENUM, MULTI_ENUM -> {
                        String[] enumResults = patrolObject.getEnumResult().split(",");
                        String[] enumConverts = patrolObject.getEnumConvert().split(",");
                        for (int i = 0; i < enumResults.length; i++) {
                            if (Objects.equals(enumResults[i], result)) {
                                patrolResult.setConvertValue(enumConverts[i]);
                                break;
                            }
                        }
                    }
                    case LED -> {
                        Integer afterPointCountConvert = patrolObject.getAfterPointCountConvert();
                        if (!result.contains(".") && Objects.equals(afterPointCountConvert,0)) {
                            BigDecimal value = new BigDecimal(result);
                            BigDecimal point = BigDecimal.valueOf(Math.pow(10, afterPointCountConvert));
                            double v = value.divide(point).setScale(afterPointCountConvert, BigDecimal.ROUND_HALF_UP).doubleValue();
                            patrolResult.setConvertValue(String.valueOf(v));
                        }
                    }
                }
            }
        }
        // 对比结果
        // 0-未检测 1-正常 2-异常 3-视觉识别失败
        patrolResult.setStatus(1);
        String normalValue = Optional.ofNullable(standard).map(PatrolObjectStandard::getStandardValue).orElse("");
        if (Objects.equals(patrolCheckType.getIsVision(), 1) && StrUtil.isBlank(result)) {
            //视觉检测项但是没有结果，判定为失败
            patrolResult.setStatus(3);
        } else if (StrUtil.isNotBlank(normalValue) && StrUtil.isNotBlank(patrolResult.getConvertValue())) {
            switch (Optional.ofNullable(standard).map(PatrolObjectStandard::getType).orElse("-1")) {
                case "1" -> {
                    //值判定
                    patrolResult.setStatus(normalValue.contains(patrolResult.getConvertValue()) ? 1 : 2);
                }
                case "2" -> {
                    //区间判定 todo 新增和编辑去检查有没有 ,
                    String[] values = normalValue.split(",");
                    float minValue = Float.parseFloat(values[0]);
                    float maxValue = Float.parseFloat(values[1]);
                    float checkValue = Float.parseFloat(patrolResult.getConvertValue());
                    patrolResult.setStatus((minValue <= checkValue && checkValue <= maxValue) ? 1 : 2);
                }
            }
        }
        // 标准值
        patrolResult.setNormalValue(normalValue);
        // 展示在报表的值 转换后的值+单位
        patrolResult.setShowValue(Optional.ofNullable(patrolResult.getConvertValue()).orElse("") + " " + patrolObject.getUnit());
        patrolResult.setMediaUrl(normalPath);
        patrolResult.setVisionMediaUrl(visionPath);
        patrolResultService.saveOrUpdate(patrolResult);

        return patrolResult;
    }





    private String takeSoundRecord(FlowPatrolTicketsDto params) {
//        String host = "http://192.168.1.243:8080/";
        String host = "http://127.0.0.1:8080/";

        // 构造请求URL
        String deviceNo = "999"; // 假设设备编号为999
        String recordTime = "6"; // 录音时间为15秒
        String requestUrl = host + "record?deviceNo=" + deviceNo + "&recordTime=" + recordTime;

        log.info("patrol=> 录音请求地址：{}", requestUrl);

        // 发起GET请求
        String response = "";
        try {
            response = HttpUtil.get(requestUrl, 20000); // 设置超时时间
        } catch (Exception e) {
            log.error("patrol=> 录音请求失败", e);
            return null;
        }

        log.info("patrol=>录音响应数据: {}", response);

        // 解析JSON响应
        JSONObject jsonResponse = JSONObject.parseObject(response);
        if (!jsonResponse.containsKey("code") || !jsonResponse.getInteger("code").equals(200)) {
            log.warn("patrol=> 录音请求未成功，响应码: {}", jsonResponse.getInteger("code"));
            return null;
        }

        String relativePath = jsonResponse.getJSONObject("data").getString("relativePath");
        log.info("patrol=> 录音文件路径: {}", relativePath);

        String baseUrl = getBaseUrl(requestUrl);
        String url = baseUrl + "file/" + relativePath;
        log.info("patrol=> 录音文件路径地址 {}", url);
        return url;
    }

    private String getBaseUrl(String fullUrl) {
        try {
            URL url = new URL(fullUrl);
            return url.getProtocol() + "://" + url.getHost() + ":" + url.getPort() + "/";
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }


    private void uploadReport(Integer x, Integer dir, FlowContextDto dto, FlowPatrolTicketsDto params, JSONObject jsonObject, String relativePath) {
        Integer code = jsonObject.getInteger("code");
        String result = "0";
        String path = relativePath;
        String normalValue = "0";
        if (Objects.equals(code, 200)) {
            if (StrUtil.isNotBlank(jsonObject.getString("result"))) {
                result = jsonObject.getString("result").replace("a", "").replace("b", "").replace("c", "");
            }
            if (StrUtil.isNotBlank(jsonObject.getString("path"))) {
                String visionPath = downloadImage(jsonObject.getString("path"));
                if (StrUtil.isNotBlank(visionPath)) {
                    path = visionPath;
                }
            }
            if (StrUtil.isNotBlank(jsonObject.getString("normal_value"))) {
                normalValue = jsonObject.getString("normal_value");
            }
        }
        Integer patrolItemId = params.getPatrolItemId();
        PatrolItem item = patrolItemService.getById(patrolItemId);
        PatrolObject patrolObject = patrolObjectService.getById(item.getPatrolObjectId());
        PatrolCheckType checkType = patrolCheckTypeService.getById(patrolObject.getPatrolCheckTypeId());
        PatrolObjectStandard standard = patrolObjectStandardService.getOne(Wrappers.<PatrolObjectStandard>lambdaQuery().eq(PatrolObjectStandard::getPatrolObjectId, patrolObject.getId()).last("limit 1"));
        PatrolResultEntity patrolResult = patrolResultService.getOne(Wrappers.<PatrolResultEntity>lambdaQuery().eq(PatrolResultEntity::getTicketsId, dto.getTickets().getId()).eq(PatrolResultEntity::getItemId, params.getPatrolItemId()).last("limit 1"));
        //新增
        patrolResult.setId(null);
        String direction = dir > 0 ? "-往" : "-返";
        Integer itemId = (x / 1000) * 10 + (dir > 0 ? 0 : 1);
        patrolResult.setItemId(itemId);
        patrolResult.setDevName("轨道" + (x / 1000) + "米处" + direction);
        patrolResult.setCheckTime(new Date());
        //处理结果数据
        patrolResult.setVisionResult(result);
        patrolResult.setConvertValue(result);
        normalValue = Optional.ofNullable(standard).map(PatrolObjectStandard::getStandardValue).orElse(normalValue);
        if (Objects.equals(patrolObject.getIsConvert(), 1) && StrUtil.isNotBlank(result)) {
            // 转换后的值,用来比较和做数据统计的
            // 0-无返回 1-浮点型 2-单个枚举 3-多个枚举 4-字符串  todo 前端加5-数显
            String resultType = checkType.getResultType();
            ResultTypeEnum resultTypeEnum = ResultTypeEnum.fromType(resultType);
            if (resultTypeEnum != null) {
                switch (resultTypeEnum) {
                    //todo 新增和编辑去检查有没有 ,
                    case FLOAT -> {
                        String[] convertValues = patrolObject.getFloatConvert().split(",");
                        BigDecimal convertMinValue = new BigDecimal(convertValues[0]);
                        BigDecimal convertMaxValue = new BigDecimal(convertValues[1]);
                        BigDecimal visionResult = new BigDecimal(result);
                        double convertValue = visionResult.multiply(convertMaxValue.subtract(convertMinValue)).add(convertMinValue).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        patrolResult.setConvertValue(String.valueOf(convertValue));
                        // 处理正常范围
                        if (StrUtil.isNotBlank(params.getVisionNormalValue())) {
                            String[] split = params.getVisionNormalValue().split(" ");
                            BigDecimal normalMinResult = new BigDecimal(split[Math.min(0, split.length - 1)]);
                            BigDecimal normalMaxResult = new BigDecimal(split[Math.min(1, split.length - 1)]);
                            double normalMin = normalMinResult.multiply(convertMaxValue.subtract(convertMinValue)).add(convertMinValue).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            double normalMax = normalMaxResult.multiply(convertMaxValue.subtract(convertMinValue)).add(convertMinValue).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            normalValue = normalMin + "," + normalMax;
                        }
                    }
                    case SINGLE_ENUM, MULTI_ENUM -> {
                        //todo 新增和编辑去检查有没有 , 还有数量关系
                        String[] enumResults = patrolObject.getEnumResult().split(",");
                        String[] enumConverts = patrolObject.getEnumConvert().split(",");
                        for (int i = 0; i < enumResults.length; i++) {
                            if (Objects.equals(enumResults[i], result)) {
                                patrolResult.setConvertValue(enumConverts[i]);
                                break;
                            }
                        }
                    }
                    case LED -> {
                        //todo 前端要加
                        Integer afterPointCountConvert = patrolObject.getAfterPointCountConvert();
                        if (!result.contains(".") && Objects.equals(afterPointCountConvert, 0)) {
                            BigDecimal value = new BigDecimal(result);
                            BigDecimal point = BigDecimal.valueOf(Math.pow(10, afterPointCountConvert));
                            double v = value.divide(point).setScale(afterPointCountConvert, BigDecimal.ROUND_HALF_UP).doubleValue();
                            patrolResult.setConvertValue(String.valueOf(v));
                        }
                    }
                }
            }
        }
        // 对比结果
        // 0-未检测 1-正常 2-异常 3-视觉识别失败
        patrolResult.setStatus(1);
        if (Objects.equals(checkType.getIsVision(), 1) && StrUtil.isBlank(result)) {
            //视觉检测项但是没有结果，判定为失败
            patrolResult.setStatus(3);
        } else if (StrUtil.isNotBlank(normalValue) && StrUtil.isNotBlank(patrolResult.getConvertValue())) {
            //都是转换后的进行对比
            switch (Optional.ofNullable(standard).map(PatrolObjectStandard::getType).orElse("-1")) {
                case "1" -> {
                    //值判定
                    patrolResult.setStatus(normalValue.contains(patrolResult.getConvertValue()) ? 1 : 2);
                }
                case "2" -> {
                    //区间判定 todo 新增和编辑去检查有没有 ,
                    String[] values = normalValue.split(",");
                    float minValue = Float.parseFloat(values[0]);
                    float maxValue = Float.parseFloat(values[1]);
                    float checkValue = Float.parseFloat(patrolResult.getConvertValue());
                    patrolResult.setStatus((minValue <= checkValue && checkValue <= maxValue) ? 1 : 2);
                }
            }
        }
        // 标准值
        patrolResult.setNormalValue(StrUtil.isNotBlank(normalValue) ? normalValue.replace(",", "~") + patrolObject.getUnit() : normalValue);
        // 展示在报表的值 转换后的值+单位
        String showValue = StrUtil.isBlank(patrolObject.getUnit()) ? patrolResult.getConvertValue() : StrUtil.isBlank(patrolResult.getConvertValue()) ? "" : patrolResult.getConvertValue() + patrolObject.getUnit();
        patrolResult.setShowValue(showValue);
        patrolResult.setMediaUrl(relativePath);
        patrolResult.setVisionMediaUrl(path);
        patrolResultService.saveOrUpdate(patrolResult);
        // 报警
        Runnable runnableTask = () -> {
            //todo 上传到服务端 0-未上传 1-已上传 2-上传失败
            patrolResultService.upload2Server(patrolResult);
            patrolResult.setUploadStatus(1);
            patrolResultService.saveOrUpdate(patrolResult);
        };
        dynamicDetectPool.submit(runnableTask);
    }
    private JSONObject detectSound(PatrolCheckType checkType,  String relativePath) {

        //视觉项
        String visionUrl = checkType.getVisionUrl();
        String type = checkType.getVisionType();
        Robot robot = robotService.getDefaultRobot();
        String externalIp = StrUtil.isBlank(robot.getExternalIp()) ? "127.0.0.1" : robot.getExternalIp();
        String externalHost = StrUtil.isBlank(robot.getExternalPort()) ? externalIp + ":" + serverProperties.getPort() : externalIp + ":" + robot.getExternalPort();
//        String host = (visionUrl.contains("127.0.0.1") || visionUrl.contains("localhost")) ? "127.0.0.1:" + serverProperties.getPort() : externalHost;
        // 编码，避免#等特殊符号
//        String url = "http://" + host + "/file/" + relativePath;
        String url = relativePath;
        HashMap<String, Object> query = new HashMap<>();
        query.put("url", url);
        query.put("rectype", Integer.parseInt(type));
        log.info("patrol=> 视觉地址：{},参数:{}", visionUrl, JSONObject.toJSONString(query));
        String result = "";
        try {
            result = HttpUtil.post(visionUrl, JSONObject.toJSONString(query), 15000);
        } catch (Exception e) {
            log.info("视觉检测失败", e);
        }
//        result = "{\"code\": 200, \"message\": \"voice reconginize success!\", \"result\": \"1\", \"path\":\n" +
//                "\"http://192.168.100.100:48060/img_out/1_detect_voice/20250627/result/20250627093434.jpg\"}";
        log.info("patrol=> 视觉检测结果: {}", result);
        return JSONObject.parseObject(result);
    }

    private JSONObject detect(FlowPatrolTicketsDto params, String relativePath) {
        Integer patrolItemId = params.getPatrolItemId();
        PatrolItem patrolItem = patrolItemService.getById(patrolItemId);
        PatrolObject patrolObject = patrolObjectService.getById(patrolItem.getPatrolObjectId());
        PatrolCheckType checkType = patrolCheckTypeService.getById(patrolObject.getPatrolCheckTypeId());
        //视觉项
        String visionUrl = checkType.getVisionUrl();
        String type = checkType.getVisionType();
        Robot robot = robotService.getDefaultRobot();
        String externalIp = StrUtil.isBlank(robot.getExternalIp()) ? "127.0.0.1" : robot.getExternalIp();
        String externalHost = StrUtil.isBlank(robot.getExternalPort()) ? externalIp + ":" + serverProperties.getPort() : externalIp + ":" + robot.getExternalPort();
        String host = (visionUrl.contains("127.0.0.1") || visionUrl.contains("localhost")) ? "127.0.0.1:" + serverProperties.getPort() : externalHost;
        // 编码，避免#等特殊符号
        String url = "http://" + host + "/file/" + URLUtil.encode(relativePath);
        HashMap<String, Object> query = new HashMap<>();
        query.put("url", url);
        query.put("rectype", Integer.parseInt(type));
        log.info("patrol=> 视觉地址：{},参数:{}", visionUrl, JSONObject.toJSONString(query));
        String result = "";
        try {
            result = HttpUtil.post(visionUrl, JSONObject.toJSONString(query), 15000);
        } catch (Exception e) {
            log.info("patrol=> 视觉检测失败", e);
        }
        log.info("patrol=> 视觉检测结果: {}", result);
//        result = "{\"code\": 200, \"message\": \"voice reconginize success!\", \"result\": \"1\", \"path\":\n" +
//                "\"http://192.168.100.100:48060/img_out/1_detect_voice/20250627/result/20250627093434.jpg\"}";
        return JSONObject.parseObject(result);
    }


    private String takePic(FlowPatrolTicketsDto params) {
        RobotEquipment channel = robotEquipmentService.getById(params.getDetectEquipmentId());
        IEquipmentService service = equipmentFactory.getServiceByBrand(channel.getBrand());
        // /日期/巡检对象
        PatrolItemVo item = patrolItemService.getVoById(params.getPatrolItemId());
        String folder = "patrol" + File.separator + DateUtil.format(new Date(), "yyyyMMdd") + File.separator + item.getPatrolObjectStr();
        //MediaFileDto mediaFileDto = service.takePic(channel.getIp(), channel.getChannel(), fileProperties.getLocal().getBasePath(), folder);
        TakePicParamsDto paramsDto = new TakePicParamsDto();
        paramsDto.setBasePath(fileProperties.getLocal().getBasePath());
        paramsDto.setFolder(folder);
        QueryParamsDto queryParamsDto = new QueryParamsDto();
        queryParamsDto.setPassword(channel.getPassword());
        queryParamsDto.setUsername(channel.getUsername());
        queryParamsDto.setPort(channel.getPort());
        queryParamsDto.setChannel(channel.getChannel());
        queryParamsDto.setIp(channel.getIp());
        MediaFileDto mediaFileDto = (MediaFileDto) service.executeCmd(queryParamsDto, true, EquipmentCmdEnum.TAKE_PIC, paramsDto);
        log.info("patrol=> 拍照结果 {}", mediaFileDto);
        return mediaFileDto.getRelativePath();
    }


    /**
     * 下载图片到本地
     *
     * @param imageUrl 视觉 url
     * @return url 本地的相对路径
     */
    private String downloadImage(String imageUrl) {
        InputStream in = null;
        String relativePath = File.separator + "vision_draw" + File.separator + DateUtil.format(new Date(), "yyyyMMdd") + File.separator + DateUtil.format(new Date(), "yyyyMMddHHmmssSSS") + ".jpg";
        String path = fileProperties.getLocal().getBasePath() + relativePath;
        try {  // 打开输入流
            URL url = new URL(imageUrl.replace("/./", "/"));  // 创建 URL 对象
            in = url.openStream();
            FileUtil.writeFromStream(in, path);
            return relativePath;
        } catch (IOException e) {
            log.error("patrol=> down vision picture error:{}", e.getMessage());
            return "";
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                log.error("InputStream close error:{}", e.getMessage());
            }
        }
    }


}